﻿using System;
using System.IO;
using System.Threading;

namespace Core.Framework
{
    public class FileChangeDetect
    {
        /// <summary>
        /// 定时器触发间隔
        /// </summary>
        private int TimeoutMillis { get; set; }
        private string Directory { get; set; }
        private string FilterType { get; set; }
        private string filePath { get; set; }
        private EventValue Event { get; set; }

        private readonly FileSystemWatcher watcher = new FileSystemWatcher();


        public FileChangeDetect(string filePath) : this(filePath, 1000)
        {

        }

        public FileChangeDetect(string filePath, int timeoutMillis)
        {
            this.TimeoutMillis = timeoutMillis;
            this.Directory = Path.GetDirectoryName(filePath);
            this.FilterType = $"*{Path.GetExtension(filePath)}";
            this.filePath = filePath;

            this.WatcherStart();
        }

        /// <summary>
        /// 初始化监听
        /// </summary>
        /// <param name="directory">需要监听的目录</param>
        /// <param name="filterType">需要监听的文件类型(筛选器字符串)</param>
        /// <param name="IsEnableRaising">是否启用监听</param>
        /// <param name="IsInclude">是否监听子目录</param>
        private void WatcherStart()
        {
            watcher.BeginInit();
            watcher.Filter = FilterType;
            watcher.IncludeSubdirectories = false;
            watcher.EnableRaisingEvents = true;
            watcher.NotifyFilter = NotifyFilters.LastWrite;
            watcher.Path = this.Directory;

            watcher.Changed += (sender, e) =>
            {
                LoggerUtils.Write($"FileChangeDetect:{e.FullPath.Equals(filePath)} - {e.FullPath} - {filePath}");

                if (e.FullPath.Equals(filePath))
                {
                    this.OnWatchedFileChange(null);
                    //this.Event.Timer.Change(TimeoutMillis, Timeout.Infinite);
                }
            };

            watcher.EndInit();
        }

        public void StartWaitResult(Action<string> action)
        {
            this.Event = new EventValue
            {
                Action = action,
                Timer = new Timer(new TimerCallback(OnWatchedFileChange), null, Timeout.Infinite, Timeout.Infinite)
            };
        }

        private void OnWatchedFileChange(object state)
        {
            if (this.Event == null)
                return;

            try
            {
                LoggerUtils.Write($"FileChangeDetect OnWatchedFileChange:{File.Exists(this.filePath)}");

                if (File.Exists(this.filePath))
                {
                    var content = File.ReadAllText(this.filePath);
                    this.Event.Action.Invoke(content);
                }
            }
            catch (Exception ex)
            {
                LoggerUtils.Write($"FileChangeDetect Exception:{ex.TryToJson()}");
            }
        }
    }

    public class EventValue
    {
        public string OldValue { get; set; }
        public Timer Timer { get; set; }
        public Action<string> Action { get; set; }
    }
}


